package com.lazy.mongodemo;

import java.util.Date;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.bson.Document;
import org.bson.types.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lazy.lib.util.DateUtil;
import com.lazy.mongodemo.DemoInsertMt.Worker;
import com.mongodb.Block;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
import com.mongodb.MongoCredential;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;

import static com.mongodb.client.model.Filters.*;

public class DemoQueryMtGps {
    private static final Logger logger = LoggerFactory.getLogger(DemoQueryMtGps.class);

    private MongoClient client;
    private MongoCollection<Document> coll;
    
    
    public DemoQueryMtGps(String url){
        // List<MongoCredential> credentials = new ArrayList<MongoCredential>();
        // credentials.add(MongoCredential.createCredential("sms_test", "ecodeSms", "sms_test".toCharArray()));
        //client = new MongoClient(new ServerAddress("127.0.0.1", 27017), credentials);
        //client = new MongoClient(host, port);
        MongoClientURI connectionString = new MongoClientURI(url);
        client = new MongoClient(connectionString);
 
        MongoDatabase db = client.getDatabase("gwgps");
        coll = db.getCollection("location");
    }
    
    public void testQuery2() {
   // now use a range query to get a larger subset
      int count = 0;
      long startTime = System.currentTimeMillis();
      Block<Document> printBlock = new PrintBlock(count); 

      coll.find(and(gt("_id", getObjectId("2015-12-20 08:00:00")),lte("_id", getObjectId("2015-12-20 08:00:10")))).forEach(printBlock);
      long endTime = System.currentTimeMillis();
      logger.info("total count  {}  ", count);
      logger.info("query 10s takes time  {}  ", (endTime - startTime));
    }
    
    static class PrintBlock implements Block<Document> {
        int count = 0;
        public PrintBlock(int count){
            this.count = count;
        }
        @Override
        public void apply(final Document document) {
            count++;
            // logger.info("{}", document.toJson());
        }
    };
    
    public void testQuery() {
        long startTime = System.currentTimeMillis();
        MongoCursor<Document> cursor = coll.find(
                and(gt("_id", getObjectId("2015-12-20 08:00:00")),lte("_id", getObjectId("2015-12-20 08:00:10")))).iterator();
        
        int count = 0;
        try {
            while (cursor.hasNext()) {
                count++;
                cursor.next();
                //logger.info("{}", cursor.next().toJson());
            }
        } finally {
            cursor.close();
        }
        long endTime = System.currentTimeMillis();
        //logger.info("endTime  {}  ", endTime);
        logger.info("total count  {}  ", count);
        logger.info("query takes time  {}  ", (endTime - startTime));
    }
    
    
    public ObjectId getObjectId(String strDate) {
        
        ObjectId objectId = new ObjectId();
        Date date = DateUtil.parseStrDate(strDate, "yyyy-MM-dd HH:mm:ss");
        long tick = date.getTime()/1000;
        
        return new ObjectId(Long.toHexString(tick) + "0000000000000000");
    }
    
    public static void main(String[] args){
        
//        String host = "127.0.0.1";
       // String host = "192.168.1.234";
        //int port = 27017;
        int count = 10;
        int poolCount = 4;
        String url = "mongodb://192.168.1.234:37017";
        if (args.length == 3) {
            url = args[0];
            count = Integer.valueOf(args[1]);
            poolCount = Integer.valueOf(args[2]);
        }
        logger.info("connecting to mongodb {}  group count {} poolCount {}", url, count, poolCount);
        DemoQueryMtGps demo = new DemoQueryMtGps(url);
        
        ExecutorService executorService = Executors.newFixedThreadPool(poolCount);
        long startTime = System.currentTimeMillis();

        CountDownLatch latch = new CountDownLatch(count);
        for (int i = 0; i < count; i++) {
            executorService.submit(new Worker(demo, latch));
        }
        
        try{
            latch.await();
        }catch(InterruptedException e){
            e.printStackTrace();
        }
        executorService.shutdown();
        long endTime = System.currentTimeMillis();
        logger.info("all take time {} ms", (endTime - startTime));
    }
    
    
    
    static class Worker implements Runnable { 
        CountDownLatch latch;
        DemoQueryMtGps demoQuery;
        
        public Worker(DemoQueryMtGps demoQuery, CountDownLatch latch){
            this.demoQuery = demoQuery;
            this.latch = latch;
        }
        
        public void run() { 
            try{
                demoQuery.testQuery();
            }catch(Exception e){
                e.printStackTrace();
            }finally{
                latch.countDown();
            }

        }
    }

}
